# 有时候，需要将一系列字典存储在列表中，或将列表作为值存储在
# 字典中，这称为嵌套 。你可以在列表中嵌套字典、在字典中嵌套
# 列表甚至在字典中嵌套字典。正如下面的示例将演示的，嵌套是一项强大的功能。

# 字典列表
alien_0 = {'color': 'green', 'points': 5}
alien_1 = {'color': 'yellow', 'points': 10}
alien_2 = {'color': 'red', 'points': 15}

aliens = [alien_0, alien_1, alien_2]

for alien in aliens:
	print(alien)


# 更符合现实的情形是，外星人不止三个，且每个外星人都是使用代
# 码自动生成的。在下面的示例中，使用range() 生成了30个外星人：
aliens = []

# 创建30个绿色的外星人
for alien_number in range(30):
	new_alien = {'color': "green", 'point': 5, 'speed': 'slow'}
	aliens.append(new_alien)

# 显示前5个外星人
for alien in aliens[:5]:
	print(alien)
print("...")

# 显示创建了多少个外星人
print(f"Total number of aliens: {len(aliens)}.")

# 这些外星人都具有相同的特征，但在Python看来，每个外星人都是独立的，这让我们能够独立地修改每个外星人

# 在什么情况下需要处理成群结队的外星人呢？想象一下，可能随着
# 游戏的进行，有些外星人会变色且加快移动速度。必要时，可使
# 用for 循环和if 语句来修改某些外形人的颜色。例如，要将前三
# 个外星人修改为黄色、速度为中等且值10分，可这样做
aliens = []

# 创建30个绿色的外星人
for alien_number in range(30):
	new_alien = {'color': "green", 'points': 5, 'speed': 'slow'}
	aliens.append(new_alien)

for alien in aliens[:3]:
	if alien['color'] == 'green':
		alien['color'] = 'yellow'
		alien['speed'] = 'medium'
		alien['points'] = 10

# 显示前5个外星人
for alien in aliens[:5]:
	print(alien)
print('...')



# 在字典中存储列表

# 有时候，需要将列表存储在字典中，而不是将字典存储在列表中。
# 例如，你如何描述顾客点的比萨呢？如果使用列表，只能存储要添
# 加的比萨配料；但如果使用字典，就不仅可在其中包含配料列表，还可包含其他有关比萨的描述。
# 在下面的示例中，存储了比萨的两方面信息：外皮类型和配料列表。
# 配料列表是一个与键'toppings' 相关联的值。要访问该列表，我们使用字典名和键'toppings' ，
# 就像访问字典中的其他值一样。这将返回一个配料列表，而不是单个值：

# 存储所点披萨的信息
pizza = {
	'crust': 'thick',
	'toppings': ['mushrooms', 'extra cheese']
}

# 概述所点的披萨
print(f"You ordered a {pizza['crust']}-crust pizza, "
	"with the following toppings:")
# 如果函数调用print() 中的字符串很长，可以在合适的位置分行。
# 只需要在每行末尾都加上引号，同时对于除第一行外的其他各行，都在行首加上引号并缩进。
# 这样，Python将自动合并圆括号内的所有字符串

for topping in pizza['toppings']:
	print(f"\t{topping}")


# 每当需要在字典中将一个键关联到多个值时，都可以在字典中嵌套
# 一个列表。在本章前面有关喜欢的编程语言的示例中，如果将每个
# 人的回答都存储在一个列表中，被调查者就可选择多种喜欢的语
# 言。在这种情况下，当我们遍历字典时，与每个被调查者相关联的
# 都是一个语言列表，而不是一种语言；因此，在遍历该字典的for
# 循环中，我们需要再使用一个for 循环来遍历与被调查者相关联的语言列表：
favorite_languages = {
	'jen': ['python', 'ruby'],
	'sarah': ['c'],
	'edward': ['ruby', 'go'],
	'phil': ['python', 'haskell'],
}

for name, languages in favorite_languages.items():
	print(f"\n{name.title()}'s favorite languages are:")
	for language in languages:
		print(f"\t{language.title()}")

# 为进一步改进这个程序，可在遍历字典的for 循环开头添加一条if
# 语句，通过查看len(languages) 的值来确定当前的被调查者喜欢
# 的语言是否有多种。如果他喜欢的语言有多种，就像以前一样显示
# 输出；如果只有一种，就相应修改输出的措辞，如显示Sarah's favorite language is C 。

# 注意 　列表和字典的嵌套层级不应太多。如果嵌套层级比前面的示例多得多，很可能有更简单的解决方案。



# 在字典中存储字典

# 可在字典中嵌套字典，但这样做时，代码可能很快复杂起来。例
# 如，如果有多个网站用户，每个都有独特的用户名，可在字典中将
# 用户名作为键，然后将每位用户的信息存储在一个字典中，并将该
# 字典作为与用户名相关联的值。在下面的程序中，存储了每位用户
# 的三项信息：名、姓和居住地。为访问这些信息，我们遍历所有的
# 用户名，并访问与每个用户名相关联的信息字典
users = {
	'aeinstein':{
		'first': 'albert',
		'last': 'einstein',
		'location': 'princeton'
	},
	'mcurie':{
		'first': 'marie',
		'last': 'curie',
		'location': 'paris'
	}
}

for username, user_info in users.items():
	print(f"\nUsername: {username}")
	full_name = f"{user_info['first']} {user_info['last']}"
	location = user_info['location']

	print(f"\tFull name: {full_name.title()}")
	print(f"\tLocation: {location.title()}")

# 注意，表示每位用户的字典都具有相同的结构。虽然Python并没
# 有这样的要求，但这使得嵌套的字典处理起来更容易。倘若表示每
# 位用户的字典都包含不同的键，for 循环内部的代码将更复杂

